package com.cdks.wuxiu.api.service;

import lombok.extern.slf4j.Slf4j;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.cdks.wuxiu.api.component.cdks.kmsg.SingleMessage;
import com.cdks.wuxiu.api.component.constant.Constant;
import com.cdks.wuxiu.api.component.constant.ScoreEnum;
import com.cdks.wuxiu.api.service.mysql.BookConsultInfoService;
import com.cdks.wuxiu.api.service.mysql.UserBillInfoService;
import com.cdks.wuxiu.api.service.mysql.UserScoreInfoService;
import com.cdks.wuxiu.api.service.mysql.UserWalletInfoService;
import com.cdks.wuxiu.api.util.SmsUtils;
import com.cdks.wuxiu.api.util.TimeUtils;
import com.cdks.wuxiu.entity.message.ChatPrivateData;
import com.cdks.wuxiu.entity.mysql.BookConsultInfo;


@Slf4j
@Service
public class BookServiceImpl implements BookService {
    @Resource
    private BookConsultInfoService bookConsultInfoService;
    @Resource
    private UserWalletInfoService userWalletInfoService;
    @Resource
    private UserScoreInfoService userScoreInfoService;    
    @Resource
    private UserBillInfoService userBillInfoService;   


    private int saveRefundBill(long cost, long earnerId, long orderId)
    {       
        int ret  = userBillInfoService.saveBill(cost, cost, cost, 0, cost, Constant.USERID_SYSTEM, earnerId, Constant.COST_TYPE_BEAN, Constant.COST_TYPE_BEAN, orderId, "预约咨询退费");
        if (ret < 0)
        {
            log.error("book save refund bill failed");

            return -1;
        }

        return 0;
    }

    private int saveCostBill(long cost, long payerId, long earnerId, int payType, int earnType, long orderId, String remark)
    {       
        int ret  = userBillInfoService.saveBill(cost, cost, cost, 0, cost, payerId, earnerId, payType, earnType, orderId, remark);
        if (ret < 0)
        {
            log.error("book save cost bill failed");

            return -1;
        }

        return 0;
    }

    @Override
    public int payCost(long payerId, int cost, long orderId, String remark) {
        if (cost == 0)
        {
            return 0;
        }

        //预约咨询不能使用积分，因为积分会过期
        int ret  = userWalletInfoService.decBean(payerId, cost, Constant.STATIS_TYPE_CONSUME, Constant.PAY_MODE_FIRST);
        if (ret < 0)
        {
            return -1;
        }

        //保存定金或押金账单
        saveCostBill(cost, payerId, Constant.USERID_SYSTEM, Constant.COST_TYPE_BEAN, Constant.COST_TYPE_BEAN, orderId, remark); 

        return 0;
    }

    @Override
    public int createSheet(BookConsultInfo order) {
        int ret  = bookConsultInfoService.createSheet(order);
        if (ret < 0)
        {
            return -1;
        }

        return 0;
    }

    @Override
    public BookConsultInfo getSheetByOrderNo(String orderNo) {
        return bookConsultInfoService.getSheetByOrderNo(orderNo);
    }

    @Override
    public BookConsultInfo getBusySheetByUser(long userId, long time) {
        return bookConsultInfoService.getBusySheetByUser(userId, time);
    }

    @Override
    public BookConsultInfo getBusySheetAnyUser(long userId, long recverId, long time) {
        return bookConsultInfoService.getBusySheetAnyUser(userId, recverId, time);
    }

    @Override
    public BookConsultInfo getBusySheetBothUser(long payerId, long earnerId, long time) {
        return bookConsultInfoService.getBusySheetBothUser(payerId, earnerId, time);
    }

    @Override
    public BookConsultInfo getPlanSheetByUser(long userId, long startTime, long expireTime) {
        return bookConsultInfoService.getPlanSheetByUser(userId, startTime, expireTime);
    }

    @Override
    public BookConsultInfo getPlanSheetAnyUser(long userId, long recverId, long startTime, long expireTime) {
        return bookConsultInfoService.getPlanSheetAnyUser(userId, recverId, startTime, expireTime);
    }

    @Override
    public int paySheet(BookConsultInfo order) {
        return bookConsultInfoService.paySheet(order);
    }

    @Override
    public int confirmSheet(BookConsultInfo order) {
        return bookConsultInfoService.confirmSheet(order);
    }

    @Override
    public int signInSheet(BookConsultInfo order, int lastStatus) {
        return bookConsultInfoService.signInSheet(order, lastStatus);
    }

    @Override
    public int changeSheet(BookConsultInfo order) {
        return bookConsultInfoService.changeSheet(order);
    }

    @Override
    public int finishSheet(BookConsultInfo order) {
        int ret  = bookConsultInfoService.finishSheet(order);
        if (ret < 0)
        {
            return -1;
        }

        log.info("book finish: order = " + order);

        //双方都未签到，均全额退费
        if (order.getSignInStatus() == Constant.BOOK_SIGNIN_NONE)
        {
            if ((order.getCost() > 0) && ((order.getPayStatus() & Constant.BOOK_PAYED_PAYER) > 0))
            {
                //给付费方退费
                userWalletInfoService.addBean(order.getPayer(), order.getCost(), Constant.STATIS_TYPE_CONSUME);
                //保存退费账单
                saveRefundBill(order.getCost(), order.getPayer(), order.getId());
            }
            
            if ((order.getSurety() > 0) && ((order.getPayStatus() & Constant.BOOK_PAYED_EARNER) > 0))
            {
                //给收益方退费
                userWalletInfoService.addBean(order.getEarner(), order.getSurety(), Constant.STATIS_TYPE_CONSUME);
                //保存退费账单
                saveRefundBill(order.getSurety(), order.getEarner(), order.getId());
            }

            return 0;
        }

        //双方都已签到
        if (order.getSignInStatus() == Constant.BOOK_SIGNIN_BOTH)
        {
            long stopTime  = order.getStopTime();
            long expire    = order.getExpireTime();
    
            //结束时间小于开始时间，认为双方已协商一致，双方全额退费。否则正常计费
            if (stopTime < order.getStartTime())
            {
                if (order.getCost() > 0)
                {
                    //给付费方退费
                    userWalletInfoService.addBean(order.getPayer(), order.getCost(), Constant.STATIS_TYPE_CONSUME);
                    //保存退费账单
                    saveRefundBill(order.getCost(), order.getPayer(), order.getId());
                }
            }
            else
            {
                //结束时间大于到期时间，按预约时长计费
                if (stopTime > expire)
                {
                    stopTime  = expire;
                }

                //计算实际计费金额
                long cost    = (stopTime - order.getStartTime() + 59) / 60 *  order.getPrice();
                long refund  = order.getCost() - cost;
                if (refund > 0)
                {
                    //给付费方退费
                    userWalletInfoService.addBean(order.getPayer(), refund, Constant.STATIS_TYPE_CONSUME);
                    //保存退费账单
                    saveRefundBill(refund, order.getPayer(), order.getId());
                }
                
                if (cost > 0)
                {
                    //给收益方结算
                    userWalletInfoService.addCoin(order.getEarner(), cost, Constant.STATIS_TYPE_INWORK);
                    //保存结算账单
                    saveCostBill(cost, order.getPayer(), order.getEarner(), Constant.COST_TYPE_BEAN, Constant.COST_TYPE_COIN, order.getId(), "预约咨询");
                }
            }

            if (order.getSurety() > 0)
            {
                //给收益方退费
                userWalletInfoService.addBean(order.getEarner(), order.getSurety(), Constant.STATIS_TYPE_CONSUME);
                //保存退费账单
                saveRefundBill(order.getSurety(), order.getEarner(), order.getId());
            }
        }
        else
        //有一方未签到，均视为爽约（1：倾诉者已签到，咨询师结束订单，2：咨询师已签到，咨询师结束订单）
        //因为限制了只能提前10分钟签到，并且只能提前一小时取消，所以在有一方签到的前提下能走到这里，不可能是取消订单（因为只有在双方都未签到的条件下才能取消订单），只可能是结束订单（双方均已签到或者当前时间大于预定的服务开始时间）
        //所以走到这里只有一种情况：订单结束时间（因为调用finish的时候已经将结束时间更新为当前时间）大于开始时间
        {
            //给爽约人退费并补偿守约人
            long cost      = 0;//爽约人扣费和退费金额（因为爽约扣一半，所以退费和扣费金额相等）
            long absentee  = 0;
            long attender  = 0;
            long refund    = 0;//受约人退费金额
            
            if ((order.getSignInStatus() & Constant.BOOK_SIGNIN_EARNER) > 0)
            {
                cost      = order.getCost() / 2;
                absentee  = order.getPayer();
                attender  = order.getEarner();
                refund    = order.getSurety();
            }
            else
            {
                cost      = order.getSurety() / 2;
                absentee  = order.getEarner();
                attender  = order.getPayer();
                refund    = order.getCost();
            }
            
            if (refund > 0)
            {
                //给守约人退费
                userWalletInfoService.addBean(attender, refund, Constant.STATIS_TYPE_CONSUME);
                //保存退费账单
                saveRefundBill(refund, attender, order.getId());
            }

            if (cost > 0)
            {
                //给爽约人退费
                userWalletInfoService.addBean(absentee, cost, Constant.STATIS_TYPE_CONSUME);
                //保存退费账单
                saveRefundBill(cost, absentee, order.getId());
                //以积分形式补偿守约人
                long expire  = TimeUtils.getTimeSecond() + Constant.TIME_VALUE_03_DAYS;
                userScoreInfoService.addScore(attender, cost, ScoreEnum.TYPE_BOOK_ABSENT_FINE.getCode(), expire, ScoreEnum.TYPE_BOOK_ABSENT_FINE.getDesc());            
                //保存违约金账单
                saveCostBill(cost, absentee, attender, Constant.COST_TYPE_BEAN, Constant.COST_TYPE_SCORE, order.getId(), "预约咨询违约金");

                //给守约人发送通知
                ChatPrivateData data  = new ChatPrivateData();
                data.setContent("因您预约的咨询服务对方爽约，系统补偿您" + cost + "积分已到账，可消费也可提现，有效期至" + TimeUtils.getLocalDateTime("yyyy-MM-dd HH:mm:ss", expire));
                SingleMessage.sendChatMessage(Constant.USERID_SYSTEM, attender, Constant.MSG_TYPE_TEXT, Constant.ENABLE_NO, data);
                SingleMessage.sendOfflineNotice(attender, "【积分到账】", "因您预约的咨询服务对方爽约，系统补偿您的积分已到账，请前往查看");
            }
        }

        return 0;
    }

    @Override
    public int autoSignIn(BookConsultInfo order, long userId) {
        //用户是付费方
        if (order.getPayer() == userId)
        {
            //付费方尚未支付
            if ((order.getPayStatus() & Constant.BOOK_PAYED_PAYER) == 0)
            {
                //弹窗提示确认预约单
                ChatPrivateData info  = new ChatPrivateData();
                info.setContent("您与当前用户在预约的咨询时段内，但您尚未确认预约单，请先前往处理");
                info.setScheme("xinsu://book/detail?orderNo=" + order.getOrderNo());
                SingleMessage.sendChatMessage(Constant.USERID_SYSTEM, userId, Constant.MSG_TYPE_POPUP, Constant.ENABLE_NO, info);

                return -1;
            }

            //付费方迟到（已支付定金但未签到），则自动签到
            if ((order.getSignInStatus() & Constant.BOOK_SIGNIN_PAYER) == 0)
            {
                order.setSignInStatus(order.getSignInStatus() | Constant.BOOK_SIGNIN_PAYER);
                if (order.getSignInStatus() == Constant.BOOK_SIGNIN_BOTH)
                {
                    order.setStatus(Constant.BOOK_STATUS_START);
                }

                //双方同时签到，后执行的一方可能会失败
                int lastStatus  = order.getSignInStatus();
                int ret = signInSheet(order, lastStatus);
                if (ret < 0)
                {
                    //重新获取订单最新状态
                    order  = getSheetByOrderNo(order.getOrderNo());
                    lastStatus  = order.getSignInStatus();
                    order.setSignInStatus(order.getSignInStatus() | Constant.BOOK_SIGNIN_PAYER);

                    if (order.getSignInStatus() == Constant.BOOK_SIGNIN_BOTH)
                    {
                        order.setStatus(Constant.BOOK_STATUS_START);
                    }

                    ret = signInSheet(order, lastStatus);
                    if (ret < 0)
                    {
                        log.error("book sign in failed: order = " + order + ", userId =" + order.getPayer());

                        SmsUtils.sendManageNotice("用户" + order.getPayer() + "预约单签到失败");
                    }
                }
            }
        }
        
        //用户是收益方
        if (order.getEarner() == userId)
        {
            //收益方尚未支付
            if ((order.getPayStatus() & Constant.BOOK_PAYED_EARNER) == 0)
            {
                //弹窗提示确认预约单
                ChatPrivateData info  = new ChatPrivateData();
                info.setContent("您与当前用户在预约的咨询时段内，但您尚未确认预约单，请先前往处理");
                info.setScheme("xinsu://book/detail?orderNo=" + order.getOrderNo());
                SingleMessage.sendChatMessage(Constant.USERID_SYSTEM, userId, Constant.MSG_TYPE_POPUP, Constant.ENABLE_NO, info);

                return -2;
            }

            //收益方迟到（已支付押金但未签到）不能签到，需要重新预约
            if ((order.getSignInStatus() & Constant.BOOK_SIGNIN_EARNER) == 0)
            {
                //弹窗提示
                ChatPrivateData info  = new ChatPrivateData();
                info.setContent("您与当前用户在预约的咨询时段内，但您已迟到（需要支付违约金），请先结束预约单并与用户重新预约");
                info.setScheme("xinsu://book/detail?orderNo=" + order.getOrderNo());
                SingleMessage.sendChatMessage(Constant.USERID_SYSTEM, userId, Constant.MSG_TYPE_POPUP, Constant.ENABLE_NO, info);
                
                return -3;
            }
        }

        if (order.getStatus() == Constant.BOOK_STATUS_START)
        {
            return 1;
        }

        return 0;
    }

    @Override
    public List<BookConsultInfo> getRecord(long userId, int page, int start, int stop) {
        return bookConsultInfoService.getRecord(userId, page, start, stop);
    }
}
